/* $Header: apg_bus.c,v 2.3 02/04/09 13:21:19 przybyls Exp $ */

/***********************************************************************/
/*                                                                     */
/*                  Copyright Hewlett-Packard Co. 1991                 */
/*                                                                     */
/***********************************************************************/

/***********************************************************************/
/* MODULE NAME:                                                        */
/* ============                                                        */
/*                                                                     */
/* Author:                                                             */
/*                                                                     */
/* MODULE PURPOSE:                                                     */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/***********************************************************************/


/*****************************/
/*   GLOBAL INCLUDE FILES    */
/*****************************/

#include <typedefs.h>
#include <error.h>
#include <iomap.h>
#include <p_wkfile.h>
#include <wkfile.h>
#include <ramps.h>
#include <config.h>
#include <zone_config.h>
#include <zone_status.h>
#include <status.h>
#include <i_op.h>
#include <run_ui.h>
#include <exception.h>
#include <err_handler.h>
#include <readiness.h>
#include <valve.h>

/*****************************/
/*   LOCAL INCLUDE FILES     */
/*****************************/

#include "apg_bus.h"

/*****************************/
/*   GLOBAL VARIABLES        */
/*****************************/


/*****************************/
/*   EXTERNAL VARIABLES      */
/*****************************/


/*****************************/
/*   LOCAL DEFINES           */
/*****************************/


/*****************************/
/*   STATIC VARIABLES        */
/*****************************/

INT8   Apg_Prepare_Pulse_Width;
INT8   Apg_Start_Request_Pulse_Width;
INT8   Apg_Start_Pulse_Width;
INT8   Apg_Stop_Pulse_Width;

APG_BUS_STRUCT Apg_Out_Image;
APG_BUS_STRUCT Prev_Apg_In_Image;

/*****************************/
/*   IMPLEMENT SECTION       */
/*****************************/

void InitializeApgBus( void )
{
    BIT8 junk;

    /* set all APG out bits "high" except Ready */
    *(BIT8 *)&Apg_Out_Image = 0xff;
    Apg_Out_Image.Ready = 0;         /* 0 is not ready */
    APG_BUS_OUT = *(BIT8 *)&Apg_Out_Image;

    /* dummy read to enable apg outputs */
    junk = APG_BUS_IN;
    (void) junk;
}


void AssertApgPrepare ( void )
{
       Apg_Prepare_Pulse_Width = 7;   /* 7-1 = 6 * 20mSec = 120mSec */
}



void AssertApgStartRequest ( void )
{
       Apg_Start_Request_Pulse_Width = 7;   /* 7-1 = 6 * 20mSec = 120mSec */
}



void AssertApgStart ( void )
{
   /* only count from 7 to 1, use one as a flag to reset interrupt hardware */
       Apg_Start_Pulse_Width = 8;   /* 7-1 = 6 * 20mSec = 120mSec */
}



void AssertApgStop ( void )
{
       Apg_Stop_Pulse_Width = 7;   /* 7-1 = 6 * 20mSec = 120mSec */
}


void  WriteApgBus ( void )
{



      if ( Apg_Prepare_Pulse_Width > 0 )
      {
            Apg_Out_Image.Prepare = 0;
            Apg_Prepare_Pulse_Width--;
      }
      else
      {
            Apg_Out_Image.Prepare = 1;
      }

/* Vireo: No Start Request */
/*    if ( Apg_Start_Request_Pulse_Width > 0 )
      {
            Apg_Out_Image.Start_Request = 0;
            Apg_Start_Request_Pulse_Width--;
      }
      else
      {
            Apg_Out_Image.Start_Request = 1;
      }
*/

      if ( Apg_Start_Pulse_Width > 1 )
      {
            Apg_Out_Image.Start = 0;
            Apg_Out_Image.Start_Relay = 0;
            Apg_Start_Pulse_Width--;

            if ( Remote_Start_Valve != 0 )
            {
               SwitchValveImage(ON,Remote_Start_Valve);
            }
      }
      else
      {
            Apg_Out_Image.Start = 1;
            Apg_Out_Image.Start_Relay = 1;

            if ( Remote_Start_Valve != 0 )
            {
               SwitchValveImage(OFF,Remote_Start_Valve);
            }

      }


      if ( Apg_Stop_Pulse_Width > 0 )
      {
            Apg_Out_Image.Stop = 0;
            Apg_Stop_Pulse_Width--;
      }
      else
      {
            Apg_Out_Image.Stop = 1;
      }

      /*
      ** External (APG) Ready = 1, NotReady = 0.
      **
      ** Drive APG ready to "NotReady" if NotReady internally or NotReady host or if in RUN_ACTIVE or POST_RUN states.
      */
      if ( ( InternalReadyEval() != READY ) ||
           ( HostReady() != READY ) ||
           ( Run_State == RUN_ACTIVE ) ||
           ( Run_State == POST_RUN ) )
      {
            Apg_Out_Image.Ready = 0;
      }
      else
      {
            Apg_Out_Image.Ready = 1;
      }

/*    Apg_Out_Image.Shut_Down = !( TestForShutdown() || TestForNonFatalErr() ); */

      Apg_Out_Image.Reserved = 1;   /* revisit, just leave this high? */
      Apg_Out_Image.Unused_4 = 1;
      Apg_Out_Image.Unused_2 = 1;


      INTERRUPTS_OFF

      APG_BUS_OUT = *(BIT8 *)&Apg_Out_Image;

      /* reset the signal DSP start input 20 msec before end of start run pulse */
      /* the signal DSP samples this input at 16 kHz, so there must be at least 62.5 usec between transitions */
      if ( Apg_Start_Pulse_Width == 2 )
      {
          RESET_START_TO_SIG_DSP
      }

      /* re-enable the start run interrupt when run completes and start run input is false */
      if ( ( Apg_Start_Pulse_Width == 1 ) && ( !RunInProgress() ) && ( Prev_Apg_In_Image.Start == 1 ) )
      {
          Apg_Start_Pulse_Width = 0;

          ENABLE_START_RUN_INTERRUPT
      }

      INTERRUPTS_ON
}



void ApgBusDriver ( void )

{
      APG_BUS_STRUCT apg_bus;

      WriteApgBus();

      *(BIT8 *)&apg_bus =    APG_BUS_IN & VALID_VIREO_APG;

      /* set an exception if the bus is "Not Ready" */
      if ( apg_bus.Ready == 1 )
      {
          ClearNewException( EXTERNAL_DEVICE );
      }
      else
      {
          SetNewException( EXTERNAL_DEVICE, 0, 0 );
      }

      if ((( apg_bus.Prepare == 0 ) &&
           ( Prev_Apg_In_Image.Prepare == 1 )) &&   /* asserted now, wasn't before */
           ( Apg_Out_Image.Prepare == 1 ))          /* and we aren't driving it low */
      {
          AssertApgPrepare();   /* strech the pulse */
          Prepare(Auto);
      }

      /* start line generates an interrupt, don't need to poll it */

      if ((( apg_bus.Stop == 0 ) &&
           ( Prev_Apg_In_Image.Stop == 1 )) &&   /* asserted now, wasn't before */
           ( Apg_Out_Image.Stop == 1 ))          /* and we aren't driving it low */
      {
          AssertApgStop();    /* strech the pulse */
          StopRun(Abort);
      }

      Prev_Apg_In_Image = apg_bus;   /* save for next cycle */

}

INT32 ApgValue (void)
{
   APG_OUTPUT outval;

   outval.apg = Prev_Apg_In_Image;
   return (INT32) (outval.byte | UNUSED_VIREO_APG);
}
